package com.simple.core.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.simple.annotation.Observer;
import com.simple.core.Carrier;
import com.simple.core.Sender;
import com.simple.manager.impl.InstanceManager;
import lombok.AllArgsConstructor;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 发送消息的增强功能，此功能时将类中的锚点进行增强实现发送数据的功能
 */
public class EnhanceSender implements MethodInterceptor {

    /**
     * 被增强的方法名
     */
    private List<String> methods;

    public EnhanceSender(List<Method> methods) {
        this.methods = methods.stream().map(Method::toString).collect(Collectors.toList());
    }

    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        // 检查是不是被增强的锚点方法，不是就按照原始逻辑执行
        if (!CollUtil.contains(methods, method.toString())) {
            return methodProxy.invokeSuper(o, args);
        }
        // 是锚点方法，检查参数类型是否符合要求
        Class<?>[] types = method.getParameterTypes();
        if (ArrayUtil.isEmpty(types)) {
            throw new IllegalArgumentException(String.format("参数不能为空，且类型必须是：%s或%s", Carrier.class, Map.class));
        }
        Object param = args[0];
        Sender sender = (Sender) InstanceManager.getInstance().lookup(SenderImpl.class.getName());
        if (param instanceof Carrier) { // 是标准的数据载体直接发送
            return sender.send((Carrier) param);
        } else if (param instanceof Map) { // 不是标准的数据载体，而是Map对象，则转成数据载体
            // 获取事件的动作
            Observer observer = method.getDeclaredAnnotation(Observer.class);
            String value = observer.value();
            if (StrUtil.isEmpty(value)) {
                throw new IllegalArgumentException(String.format("当参数是Map时，注解：%s中的参数value必须不是null或者空字符串", Observer.class));
            }
            // 整合成标准数据载体
            Carrier carrier = new Carrier(value);
            ((Map<String, Object>) param).forEach(carrier::addData);
            // 发送事件
            return sender.send(carrier);
        } else {
            throw new IllegalArgumentException("是不支持的格式");
        }
    }
}
